package com.zhaoqi.hr.service;

import com.zhaoqi.hr.dto.request.ContractCreateRequest;
import com.zhaoqi.hr.dto.request.ContractSignRequest;
import com.zhaoqi.hr.dto.response.ContractResponse;
import com.zhaoqi.hr.entity.EmployerProfile;
import com.zhaoqi.hr.entity.JobApplication;
import com.zhaoqi.hr.entity.User;
import com.zhaoqi.hr.entity.WorkContract;
import com.zhaoqi.hr.entity.WorkerProfile;
import com.zhaoqi.hr.repository.EmployerProfileRepository;
import com.zhaoqi.hr.repository.JobApplicationRepository;
import com.zhaoqi.hr.repository.UserRepository;
import com.zhaoqi.hr.repository.WorkContractRepository;
import com.zhaoqi.hr.repository.WorkerProfileRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 合同服务
 */
@Service
public class ContractService {

    private static final Logger log = LoggerFactory.getLogger(ContractService.class);

    @Autowired
    private WorkContractRepository contractRepository;
    
    @Autowired
    private JobApplicationRepository jobApplicationRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private EmployerProfileRepository employerProfileRepository;
    
    @Autowired
    private WorkerProfileRepository workerProfileRepository;

    /**
     * 创建合同
     */
    @Transactional
    public ContractResponse createContract(Long employerId, ContractCreateRequest request) {
        log.info("雇主 {} 创建合同，申请ID: {}", employerId, request.getJobApplicationId());

        // 验证岗位申请存在且已被接受
        JobApplication application = jobApplicationRepository.findById(request.getJobApplicationId())
                .orElseThrow(() -> new RuntimeException("岗位申请不存在"));

        if (application.getStatus() != JobApplication.ApplicationStatus.ACCEPTED) {
            throw new RuntimeException("只有已接受的申请才能创建合同");
        }

        // 验证雇主权限（通过岗位关联验证）
        // 这里需要通过JobPosting来验证，暂时简化处理

        // 检查是否已存在合同
        boolean contractExists = contractRepository.existsByJobApplicationId(request.getJobApplicationId());
        if (contractExists) {
            throw new RuntimeException("该申请已存在合同");
        }

        // 生成合同编号
        String contractNumber = generateContractNumber();

        // 获取雇主和劳动者Profile
        EmployerProfile employer = employerProfileRepository.findByUserId(employerId)
                .orElseThrow(() -> new RuntimeException("雇主信息不存在"));
        WorkerProfile worker = application.getWorker();
        if (worker == null) {
            throw new RuntimeException("劳动者信息不存在");
        }

        // 创建合同
        WorkContract contract = new WorkContract();
        contract.setContractNumber(contractNumber);
        contract.setJobApplicationId(request.getJobApplicationId());
        contract.setEmployer(employer);
        contract.setWorker(worker);
        contract.setContractTitle(request.getContractTitle());
        contract.setWorkDescription(request.getWorkDescription());
        contract.setWorkLocation(request.getWorkLocation());
        contract.setStartTime(request.getStartTime());
        contract.setEndTime(request.getEndTime());
        contract.setSalary(request.getSalary());
        contract.setSalaryType(request.getSalaryType());
        contract.setPaymentMethod(request.getPaymentMethod());
        contract.setOtherTerms(request.getOtherTerms());
        contract.setRemark(request.getRemark());
        contract.setStatus(WorkContract.ContractStatus.DRAFT);
        contract.setEmployerSigned(false);
        contract.setWorkerSigned(false);
        contract.setCreatedAt(LocalDateTime.now());
        contract.setUpdatedAt(LocalDateTime.now());

        contract = contractRepository.save(contract);

        // 调用第三方电子签名服务创建合同（模拟）
        String thirdPartyContractId = createThirdPartyContract(contract);
        contract.setThirdPartyContractId(thirdPartyContractId);
        contract = contractRepository.save(contract);

        log.info("合同创建成功，ID: {}, 编号: {}", contract.getId(), contractNumber);
        return convertToResponse(contract);
    }

    /**
     * 签署合同
     */
    @Transactional
    public ContractResponse signContract(Long userId, ContractSignRequest request) {
        log.info("用户 {} 签署合同 {}", userId, request.getContractId());

        WorkContract contract = contractRepository.findById(request.getContractId())
                .orElseThrow(() -> new RuntimeException("合同不存在"));

        // 验证用户权限
        boolean isEmployer = contract.getEmployer().getUser().getId().equals(userId);
        boolean isWorker = contract.getWorker().getUser().getId().equals(userId);
        
        if (!isEmployer && !isWorker) {
            throw new RuntimeException("无权限签署此合同");
        }

        // 验证合同状态
        if (contract.getStatus() == WorkContract.ContractStatus.CANCELLED) {
            throw new RuntimeException("合同已取消，无法签署");
        }

        if (contract.getStatus() == WorkContract.ContractStatus.COMPLETED) {
            throw new RuntimeException("合同已完成，无法重复签署");
        }

        // 处理签署
        LocalDateTime now = LocalDateTime.now();
        
        if (isEmployer && "employer".equals(request.getSignType())) {
            if (contract.getEmployerSigned()) {
                throw new RuntimeException("雇主已签署，无法重复签署");
            }
            
            if (request.getAgreed()) {
                contract.setEmployerSigned(true);
                contract.setEmployerSignTime(now);
                log.info("雇主签署成功");
            } else {
                contract.setStatus(WorkContract.ContractStatus.CANCELLED);
                log.info("雇主拒绝签署，合同已取消");
            }
        } else if (isWorker && "worker".equals(request.getSignType())) {
            if (contract.getWorkerSigned()) {
                throw new RuntimeException("劳动者已签署，无法重复签署");
            }
            
            if (request.getAgreed()) {
                contract.setWorkerSigned(true);
                contract.setWorkerSignTime(now);
                log.info("劳动者签署成功");
            } else {
                contract.setStatus(WorkContract.ContractStatus.CANCELLED);
                log.info("劳动者拒绝签署，合同已取消");
            }
        } else {
            throw new RuntimeException("签署类型不匹配");
        }

        // 检查是否双方都已签署
        if (contract.getEmployerSigned() && contract.getWorkerSigned() && 
            contract.getStatus() != WorkContract.ContractStatus.CANCELLED) {
            contract.setStatus(WorkContract.ContractStatus.ACTIVE);
            log.info("合同双方签署完成，状态更新为生效");
        }

        contract.setUpdatedAt(now);
        contract = contractRepository.save(contract);

        // 调用第三方服务更新签署状态（模拟）
        updateThirdPartyContractStatus(contract);

        log.info("合同签署处理完成");
        return convertToResponse(contract);
    }

    /**
     * 获取合同详情
     */
    public ContractResponse getContractById(Long contractId) {
        WorkContract contract = contractRepository.findById(contractId)
                .orElseThrow(() -> new RuntimeException("合同不存在"));
        return convertToResponse(contract);
    }

    /**
     * 获取雇主的合同列表
     */
    public List<ContractResponse> getEmployerContracts(Long employerId) {
        List<WorkContract> contracts = contractRepository.findByEmployer_User_IdOrderByCreatedAtDesc(employerId);
        return contracts.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    /**
     * 获取劳动者的合同列表
     */
    public List<ContractResponse> getWorkerContracts(Long workerId) {
        List<WorkContract> contracts = contractRepository.findByWorker_User_IdOrderByCreatedAtDesc(workerId);
        return contracts.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    /**
     * 更新合同状态
     */
    @Transactional
    public ContractResponse updateContractStatus(Long contractId, WorkContract.ContractStatus status) {
        WorkContract contract = contractRepository.findById(contractId)
                .orElseThrow(() -> new RuntimeException("合同不存在"));

        contract.setStatus(status);
        contract.setUpdatedAt(LocalDateTime.now());
        
        contract = contractRepository.save(contract);
        
        log.info("合同状态更新成功，ID: {}, 状态: {}", contractId, status);
        return convertToResponse(contract);
    }

    /**
     * 生成合同编号
     */
    private String generateContractNumber() {
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String uuid = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
        return "CT" + dateStr + uuid;
    }

    /**
     * 调用第三方电子签名服务创建合同（模拟）
     */
    private String createThirdPartyContract(WorkContract contract) {
        // 这里应该调用法大大等第三方电子签名服务的API
        // 模拟返回第三方合同ID
        String thirdPartyId = "FADADA_" + UUID.randomUUID().toString().substring(0, 12).toUpperCase();
        log.info("模拟调用第三方服务创建合同，返回ID: {}", thirdPartyId);
        return thirdPartyId;
    }

    /**
     * 更新第三方合同签署状态（模拟）
     */
    private void updateThirdPartyContractStatus(WorkContract contract) {
        // 这里应该调用第三方服务更新签署状态
        log.info("模拟调用第三方服务更新合同签署状态，合同ID: {}", contract.getThirdPartyContractId());
    }

    /**
     * 转换为响应DTO
     */
    private ContractResponse convertToResponse(WorkContract contract) {
        ContractResponse response = new ContractResponse();
        response.setId(contract.getId());
        response.setContractNumber(contract.getContractNumber());
        response.setJobApplicationId(contract.getJobApplicationId());
        response.setEmployerId(contract.getEmployer().getUser().getId());
        response.setWorkerId(contract.getWorker().getUser().getId());
        response.setContractTitle(contract.getContractTitle());
        response.setWorkDescription(contract.getWorkDescription());
        response.setWorkLocation(contract.getWorkLocation());
        response.setStartTime(contract.getStartTime());
        response.setEndTime(contract.getEndTime());
        response.setSalary(contract.getSalary());
        response.setSalaryType(contract.getSalaryType());
        response.setPaymentMethod(contract.getPaymentMethod());
        response.setOtherTerms(contract.getOtherTerms());
        response.setStatus(contract.getStatus());
        response.setEmployerSigned(contract.getEmployerSigned());
        response.setEmployerSignTime(contract.getEmployerSignTime());
        response.setWorkerSigned(contract.getWorkerSigned());
        response.setWorkerSignTime(contract.getWorkerSignTime());
        response.setThirdPartyContractId(contract.getThirdPartyContractId());
        response.setContractFileUrl(contract.getContractFileUrl());
        response.setRemark(contract.getRemark());
        response.setCreatedAt(contract.getCreatedAt());
        response.setUpdatedAt(contract.getUpdatedAt());

        // 获取雇主和劳动者姓名
        if (contract.getEmployer() != null && contract.getEmployer().getUser() != null) {
            response.setEmployerName(contract.getEmployer().getUser().getRealName());
        }
        
        if (contract.getWorker() != null && contract.getWorker().getUser() != null) {
            response.setWorkerName(contract.getWorker().getUser().getRealName());
        }

        return response;
    }

    /**
     * 获取合同管理列表（管理员专用）
     */
    public Page<ContractResponse> getContractsForAdmin(Pageable pageable, WorkContract.ContractStatus status) {
        Specification<WorkContract> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (status != null) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<WorkContract> contractPage = contractRepository.findAll(spec, pageable);
        return contractPage.map(this::convertToResponse);
    }

    /**
     * 强制更新合同状态（管理员专用）
     */
    @Transactional
    public ContractResponse forceUpdateContractStatus(Long contractId, WorkContract.ContractStatus status, 
                                                     String reason, Long adminId) {
        WorkContract contract = contractRepository.findById(contractId)
                .orElseThrow(() -> new RuntimeException("合同不存在"));

        WorkContract.ContractStatus oldStatus = contract.getStatus();
        contract.setStatus(status);
        contract.setUpdatedAt(LocalDateTime.now());
        
        // 如果是取消合同，记录原因
        if (status == WorkContract.ContractStatus.CANCELLED || status == WorkContract.ContractStatus.TERMINATED) {
            contract.setTerminationReason(reason);
            contract.setTerminatedAt(LocalDateTime.now());
        }
        
        contract = contractRepository.save(contract);
        
        log.info("管理员强制更新合同状态，合同ID: {}, 管理员ID: {}, 原状态: {}, 新状态: {}, 原因: {}", 
                contractId, adminId, oldStatus, status, reason);
        
        return convertToResponse(contract);
    }
}
